package com.xiaomaoguai.fcp.pre.kepler.trace.interceptor;

import com.alibaba.fastjson.JSON;
import com.xiaomaoguai.fcp.pre.kepler.trace.constants.KeplerTraceConstant;
import com.xiaomaoguai.fcp.pre.kepler.router.handler.RouterInfo;
import com.xiaomaoguai.fcp.pre.kepler.router.handler.api.HandlerContext;
import com.xiaomaoguai.fcp.pre.kepler.router.handler.handlers.AbstractHandler;
import com.xiaomaoguai.fcp.pre.kepler.router.handler.handlers.EmptyHeadHandler;
import com.xiaomaoguai.fcp.pre.kepler.router.handler.handlers.RPCHandler;
import com.xiaomaoguai.fcp.pre.kepler.router.handler.handlers.TailHandler;
import io.opentracing.Span;
import io.opentracing.tag.Tags;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;

import java.util.Map;

/**
 * @author August.Zhang
 * @version v1.0.0
 * @date 2020/1/8 20:22
 * @since JDK 1.8
 */
public class CommonHandlerAroundInterceptor extends AbstractHandlerInterceptor {

	@Override
	public boolean accept(ProceedingJoinPoint pjp) {
		Class<?> clazz = pjp.getTarget().getClass();
		String typeName = pjp.getTarget().getClass().getName();
		return RPCHandler.class.isAssignableFrom(clazz) || (!StringUtils.equals(KeplerTraceConstant.STANDARD_HEAD_HANDLER_TYPE_NAME, typeName) && !TailHandler.class.isAssignableFrom(clazz) && !EmptyHeadHandler.class.isAssignableFrom(clazz) && AbstractHandler.class.isAssignableFrom(clazz));
	}

	@Override
	public void invokeBeforeMethod(ProceedingJoinPoint pjp, Span span) {
		String handlerName = pjp.getSignature().getDeclaringType().getSimpleName();
		Object[] args = pjp.getArgs();
		@SuppressWarnings("rawtypes") final HandlerContext handlerContext = (HandlerContext) args[0];
		final Map<String, Object> context = handlerContext.getBuf().getContext();
		final String productCode = (String) handlerContext.getBuf().get(KeplerTraceConstant.SPAN_TAG_PRODUCT_CODE);
		final String routerName = handlerContext.getBuf().getCurrentRouterName();
		final RouterInfo routerInfo = handlerContext.getRouterInfo();
		final String mock = routerInfo.getMock();
		final String lockKey = routerInfo.getLockKey();
		final String unLockKey = routerInfo.getUnLockKey();
		final String url = routerInfo.getUrl();
		final String rpcUrl = routerInfo.getRpcUrl();

		Tags.COMPONENT.set(span, KeplerTraceConstant.TAG_COMPONENT_VALUE_HANDLER);
		span.setTag(KeplerTraceConstant.SPAN_TAG_PRODUCT_CODE, productCode);
		span.setTag(KeplerTraceConstant.SPAN_TAG_ROUTER_NAME, routerName);
		span.setTag(KeplerTraceConstant.SPAN_TAG_HANDLER_NAME, handlerName);
		if (StringUtils.isNotBlank(url)) {
			span.setTag(KeplerTraceConstant.SPAN_TAG_URL, url);
		}
		if (StringUtils.isNotBlank(rpcUrl)) {
			span.setTag(KeplerTraceConstant.SPAN_TAG_RPC_URL, rpcUrl);
		}
		if (StringUtils.isNotBlank(lockKey)) {
			span.setTag(KeplerTraceConstant.SPAN_TAG_LOCK_KEY, lockKey);
		}
		if (StringUtils.isNotBlank(unLockKey)) {
			span.setTag(KeplerTraceConstant.SPAN_TAG_UN_LOCK_KEY, unLockKey);
		}
		if (StringUtils.isNotBlank(mock)) {
			span.setTag(KeplerTraceConstant.SPAN_TAG_MOCK, mock);
		}
		String json = JSON.toJSONString(context);
		span.setTag(KeplerTraceConstant.SPAN_TAG_BEFORE_CONVERT, jaegerDataDesensitization.dataDesensitization(json));
	}

	@Override
	public void invokeAfterMethod(ProceedingJoinPoint pjp, Span span) {
		Object[] args = pjp.getArgs();
		@SuppressWarnings("rawtypes") final HandlerContext handlerContext = (HandlerContext) args[0];
		final Map<String, Object> context = handlerContext.getBuf().getContext();

		String json = JSON.toJSONString(context);
		span.setTag(KeplerTraceConstant.SPAN_TAG_AFTER_CONVERT, jaegerDataDesensitization.dataDesensitization(json));
	}

}
